
package cn.xxl.cordova.lfrfid;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.media.MediaPlayer;
import android.content.res.AssetFileDescriptor;
import com.yonyouwl.U9ImPDA.R;

import com.android.LFRFID.SerialPort;

public class LFRFIDPlugin extends CordovaPlugin {

    private ReadThread mReadThread;

    private MediaPlayer mediaPlayer = null;

    private class ReadThread extends Thread {

        private SerialPort mSerialPort;
        private InputStream mInputStream;
        private OutputStream mOutputStream;
        private boolean mThreadRunning = true;

        public ReadThread (SerialPort serialPort) {
            mSerialPort = serialPort;

            mInputStream = serialPort.getInputStream();
            mOutputStream = serialPort.getOutputStream();

            scanStart();
        }

        public void closePort () {
            scanStop();
            mThreadRunning = false;
        }

        public void scanStart() {
            try {
                if (mOutputStream != null) {
                    mOutputStream.write(0xAA);
                }       
            } catch (Exception e) {
                e.printStackTrace();
            }   
        }
    
        public void scanStop() {
            try {
                if (mOutputStream != null) {
                    mOutputStream.write(0xBB);
                }       
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run () {
            while (mThreadRunning) {
                try {
                    if (mInputStream == null) {
                        break;
                    }
                    byte[] buffer = new byte[64]; 
                    int size = mInputStream.read(buffer, 0, 10);
                    if (size >= 8 && mThreadRunning) {
                        String input = bytesToHexString(buffer, size);
                        if (input.substring(4, 6).equals("00")) {
                            onDataReceived(input);
                        }
                    }
                    scanStop();
                    Thread.sleep(400);
                    scanStart();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (mSerialPort != null) {
                mSerialPort.close();
                mSerialPort = null;
            }
            mInputStream = null;
            mOutputStream = null;
        }
    }

    @Override
    public void initialize(final CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);

        initBeepSound();
    }

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

        if (action.equals("open")) {
            openSerialPort(callbackContext);
            return true;
        }

        if (action.equals("close")) {
            closeSerialPort();
            return true;
        }

        return false;
    }

    private void openSerialPort(final CallbackContext callbackContext) {
        cordova.getThreadPool().execute(new Runnable() {
            public void run() {
                SerialPort serialPort = null;
                try {
                    if (mReadThread != null) {
                        mReadThread.closePort();
                    }
                    serialPort = new SerialPort();
                    serialPort.Open();
                } catch (Exception e) {
                    e.printStackTrace();
                    callbackContext.error("打开LfRfid失败");
                }
                
                if (serialPort != null) {
                    mReadThread = new ReadThread(serialPort);
                    mReadThread.start();
                    callbackContext.success();
                }
            }
        });
    }

    private void closeSerialPort() {
        if (mReadThread != null) {
            mReadThread.closePort();
        }
    }

    private void initBeepSound() {
        if (mediaPlayer == null) { 
            mediaPlayer = new MediaPlayer();
            AssetFileDescriptor file = cordova.getActivity().getApplicationContext(
                ).getResources().openRawResourceFd(R.raw.beep);
            try {
                if (mediaPlayer != null) {
                    mediaPlayer.setDataSource(file.getFileDescriptor(), 
                        file.getStartOffset(), file.getLength());
                    file.close();
                    
                    mediaPlayer.prepare();
                }
            } catch (IOException e) {
                mediaPlayer = null;
            }
        }
    }

    private void playBeepSound() {
        if (mediaPlayer != null) {
            mediaPlayer.start();
        }       
    }

    private void onDataReceived(final String input) {
        playBeepSound();
        try {
            cordova.getActivity().runOnUiThread(new Runnable() {
                public void run() {
                    String jsEvent = String.format(
                            "cordova.fireDocumentEvent('LFRFID.DataReceived',{'lfrfidData':'%s'})",
                            input);
                    webView.sendJavascript(jsEvent);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String bytesToHexString(byte[] bArray, int size) {
        String ret = ""; 
        for (int i = 0; i < size; i++) { 
            String hex = Integer.toHexString(bArray[i] & 0xFF); 
            if (hex.length() == 1) { 
                hex = '0' + hex; 
            } 
            ret += hex.toUpperCase(); 
        } 
        return ret;
    } 

    @Override
    public void onDestroy() {
        closeSerialPort();
        super.onDestroy();
    }
}